#pragma once

#include <YSimpleNetwork/ITcpSession.h>
#include <YSimpleNetwork/YProactorTokenOnRecv.h>
#include <YSimpleNetwork/YProactorTokenOnSend.h>
#include <YSimpleNetwork/YProactorTokenOnDisconnect.h>
#include <YSimpleNetwork/YProactorTokenOnCancelIO.h>
#include <YSimpleNetwork/YMessageBlock.h>
#include <YSimpleNetwork/YSimpleNetwork.h>
#include <atomic>



namespace ysimple_system
{
	struct IProactor;
}

namespace ysimple_network
{
	#define RELEASE_TCP_SESSION_FUNCTOR	RELEASE_FUNCTOR(ITCPSession)	
	struct IAsyncCallback;
	
	class YEndPoint;

	class YTcpSession :
		public ITCPSession
	{
		ysimple_system::IProactor&	m_proactor;
		bool	m_reused;
		SOCKET	m_socket;
		YMessageBlock					m_messageBlock;
		IDisconectCallback*				m_pDisconnectCallback;
		RELEASE_TCP_SESSION_FUNCTOR				m_releaseFunctor;
		bool	m_disconnected;
		
	protected:
		ysimple_system::IProactor&	getProactor();
		YProactorTokenOnRecv		m_recvToken;
		YProactorTokenOnSend		m_sendToken;
		YProactorTokenOnDisconnect	m_disconnectToken;
		YProactorTokenOnCancelIO	m_cancelToken;
	public:
		YTcpSession(ysimple_system::IProactor& proactor, SOCKET socket, bool reusedSocket, RELEASE_TCP_SESSION_FUNCTOR releaseFunctor);
		virtual ~YTcpSession(void);

		bool				init(IDisconectCallback& disconnectCallback) override;
		bool				bind(const YEndPoint& endPoint) override;
		SOCKET			getSocket() const override;
		
		bool				send(PACKET_SPTR packet, ISendCallback& callback) override;
		bool				resend(ISendCallback& callback) override;
		bool				recv(IRecvCallback& callback)  override;
		bool				disconnect()  override;
		bool				reused() const override;
		void				shutdown()  override;
		void				close() override;
		bool				cancel(ICancelIOCallback& callback) override;

	private:
		std::atomic<int>			m_refCount;
	public:
		void				release() override;
		void				addRef() override;
	};

}